package cn.venny.doudian.service;

import cn.venny.doudian.DoudianClient;
import cn.venny.doudian.DoudianPage;
import cn.venny.doudian.entity.PddAllLogistics;
import cn.venny.doudian.exception.ApiException;
import cn.venny.doudian.model.bean.*;
import cn.venny.doudian.model.request.*;
import cn.venny.doudian.model.response.*;
import cn.venny.doudian.properties.DouDianProperties;
import cn.venny.doudian.utils.DateUtil;
import cn.venny.doudian.utils.RandomUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Vick C
 * @date 2021/3/27
 */
@Service
public class DoudianService {

    @Autowired
    DoudianClient doudianClient;
    @Autowired
    DouDianProperties config;
    @Autowired
    IPddAllLogisticsService pddAllLogisticsService;

    public DoudianAccessToken codeToToken(String code) {
        return doudianClient.codeToToken(code);
    }

    public String createAuthUrl() {
        String url = "https://fuwu.jinritemai.com/authorize?service_id=%s&state=%s";
        return String.format(url, config.getServiceId(), RandomUtils.random());
    }

    public DoudianAccessToken getAccessToken(String code) {
        return doudianClient.codeToToken(code);
    }


    public DoudianPage<DoudianOrder> orderList(Map<String, Object> params) {
        String accessToken = (String) params.get("accessToken");

        Integer page = (Integer) params.get("page");

        Integer day = (Integer) params.get("day");

        LocalDateTime endDate = LocalDateTime.now();
        LocalDateTime startDate = endDate.minusDays(day);

        DoudianOrderListRequest request = new DoudianOrderListRequest();
        // 2018/06/03 00:00:00
        request.setStartTime(DateUtil.localDateTimeFormat(startDate, DateUtil.YYYY_MM_DD_HH_MI_SS_SLASH));
        request.setEndTime(DateUtil.localDateTimeFormat(endDate, DateUtil.YYYY_MM_DD_HH_MI_SS_SLASH));
        // 根据创建时间排序
        request.setOrderBy("create_time");
        // 降序
        request.setIsDesc("1");
        request.setPage(page);
        // 每页订单数（默认为10，最大100）
        request.setSize(100);
        return executeQueryOrder(request, accessToken);
    }

    public List<DoudianOrder> syncOrder(String accessToen, LocalDateTime startDate, LocalDateTime endDate) {
        AtomicInteger page = new AtomicInteger();

        DoudianOrderListRequest request = new DoudianOrderListRequest();
        // 2018/06/03 00:00:00
        request.setStartTime(DateUtil.localDateTimeFormat(startDate, DateUtil.YYYY_MM_DD_HH_MI_SS_SLASH));
        request.setEndTime(DateUtil.localDateTimeFormat(endDate, DateUtil.YYYY_MM_DD_HH_MI_SS_SLASH));
        // 根据创建时间排序
        request.setOrderBy("create_time");
        // 降序
        request.setIsDesc("1");
        request.setPage(page.get());
        // 每页订单数（默认为10，最大100）
        request.setSize(100);

        List<DoudianOrder> orders = new ArrayList<>();

        recursionQueryOrder(request, accessToen, page, orders);

        return orders;
    }


    private void recursionQueryOrder(
            DoudianOrderListRequest request, String accessToken, AtomicInteger page, List<DoudianOrder> orders) {

        DoudianPage<DoudianOrder> data = executeQueryOrder(request, accessToken);
        if (data == null) {
            return;
        }

        orders.addAll(data.getPageData());

        request.setPage(page.incrementAndGet());
        recursionQueryOrder(request, accessToken, page, orders);
    }

    private DoudianPage<DoudianOrder> executeQueryOrder(DoudianOrderListRequest request, String accessToken) {
        DoudianOrderListResponse response = null;
        try {
            response = doudianClient.execute(request, accessToken);
        } catch (ApiException e) {
            throw new RuntimeException(e.getMessage());
        }

        if (response == null) {
            return null;
        }

        if (!response.isSuccess()) {
            throw new RuntimeException(response.getMessage());
        }

        if (response.getData() == null || CollectionUtils.isEmpty(response.getData().getPageData())) {
            return null;
        }

        return response.getData();
    }

    public DoudianOrderLogisticsCompanyListResponse logisticsCompanyList(String accessToken) throws ApiException {

        DoudianOrderLogisticsCompanyListRequest request = new DoudianOrderLogisticsCompanyListRequest();

        return doudianClient.execute(request, accessToken);
    }

    public void syncLogisticsCompanyToDb(String accessToken) throws ApiException {
        DoudianOrderLogisticsCompanyListResponse listResponse = logisticsCompanyList(accessToken);

        List<PddAllLogistics> list = pddAllLogisticsService.list();
        Map<String, Long> company = list.stream().collect(Collectors.toMap(PddAllLogistics::getLogisticsCompany, PddAllLogistics::getId));

        List<DoudianOrderLogisticsCompany> data = listResponse.getData();

        LocalDateTime now = LocalDateTime.now();
        List<PddAllLogistics> insertList = new ArrayList<>();


        data.forEach(d -> {
            Long id = company.get(d.getName());
            if (id == null) {
                // 数据库不存在
                PddAllLogistics p = new PddAllLogistics();
                p.setAvailable(1);
                p.setLogisticsCompany(d.getName());
                p.setCreateTime(now);
                p.setUpdateTime(now);
                p.setDoudianCode(d.getId().intValue());
                insertList.add(p);
                return;
            }
            pddAllLogisticsService.update(new LambdaUpdateWrapper<PddAllLogistics>().set(PddAllLogistics::getDoudianCode, d.getId()).eq(PddAllLogistics::getId, id));
        });


        if (CollectionUtils.isEmpty(insertList)) {
            return;
        }

        pddAllLogisticsService.saveBatch(insertList);
    }

    public DoudianOrderSearchListResponse orderSearchList(Map<String, Object> params) throws ApiException {
        String accessToken = (String) params.get("accessToken");
        DoudianOrderSearchListRequest request = new DoudianOrderSearchListRequest();
        request.setUpdateTimeStart(objToLong(params.get("updateTimeStart")));
        request.setUpdateTimeEnd(objToLong(params.get("updateTimeEnd")));
        request.setCreateTimeEnd(objToLong(params.get("createTimeEnd")));
        request.setCreateTimeStart(objToLong(params.get("createTimeStart")));
        return doudianClient.execute(request, accessToken);
    }

    private Long objToLong(Object obj) {
        if (obj == null) {
            return null;
        }
        return Long.parseLong(String.valueOf(obj));
    }

    public List<DoudianAddressAllAreas> getAllAreas(Map<String, Object> params) throws ApiException {
        String accessToken = (String) params.get("accessToken");

        DoudianAddressGetProvinceResponse provinceData = getProvince(params);

        if (provinceData == null) {
            return null;
        }

        List<DoudianAddressAllProvince> data = provinceData.getData();

        List<DoudianAddressAllAreas> areaList = new CopyOnWriteArrayList<>();

        data.forEach(province -> {
            Map<String, String> map = new HashMap<>();
            map.put("accessToken", accessToken);
            map.put("provinceId", String.valueOf(province.getProvinceId()));
            DoudianAddressGetAreasByProvinceResponse areas = null;
            try {
                areas = getAreasByProvince(map);
            } catch (ApiException e) {
                e.printStackTrace();
            }

            if (areas == null) {
                return;
            }

            List<DoudianAddressAllAreas> data1 = areas.getData();

            if (CollectionUtils.isEmpty(data1)) {
                return;
            }
            areaList.addAll(data1);
        });
        return areaList;
    }

    public DoudianAddressGetProvinceResponse getProvince(Map<String, Object> params) throws ApiException {
        String accessToken = (String) params.get("accessToken");
        DoudianAddressGetProvinceRequest request = new DoudianAddressGetProvinceRequest();
        return doudianClient.execute(request, accessToken);
    }


    public DoudianAddressGetAreasByProvinceResponse getAreasByProvince(Map<String, String> params) throws ApiException {
        String accessToken = params.get("accessToken");
        DoudianAddressGetAreasByProvinceRequest request = new DoudianAddressGetAreasByProvinceRequest();
        request.setProvinceId(params.get("provinceId"));
        return doudianClient.execute(request, accessToken);
    }
}
